using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using OracleInternal.Json.Binary;
using OracleInternal.Json.Common;

namespace OracleInternal.Json.Sql
{
	internal class OracleJsonArray : OracleJsonValue, IOracleJsonArray, IOracleJsonStructure, IOracleJsonValue, IList<OracleJsonValue>, ICollection<OracleJsonValue>, IEnumerable<OracleJsonValue>, IEnumerable
	{
		private List<OracleJsonValue> m_list;

		public int Count => m_list.Count;

		public bool IsReadOnly => false;

		public OracleJsonValue this[int index]
		{
			get
			{
				return m_list[index];
			}
			set
			{
				m_list[index] = value;
			}
		}

		internal OracleJsonArray()
		{
			m_list = new List<OracleJsonValue>();
		}

		internal OracleJsonArray(IOracleJsonArray other)
		{
			m_list = new List<OracleJsonValue>();
			foreach (OracleJsonValue item in other)
			{
				switch (item.GetOracleJsonType())
				{
				case OracleJsonType.OBJECT:
					m_list.Add(new OracleJsonObject(item.AsJsonObject()));
					break;
				case OracleJsonType.ARRAY:
					m_list.Add(new OracleJsonArray(item.AsJsonArray()));
					break;
				default:
					m_list.Add(item);
					break;
				}
			}
		}

		public override OracleJsonType GetOracleJsonType()
		{
			return OracleJsonType.ARRAY;
		}

		public int IndexOf(OracleJsonValue item)
		{
			return m_list.IndexOf(item);
		}

		public void Insert(int index, OracleJsonValue item)
		{
			m_list.Insert(index, item);
		}

		public void RemoveAt(int index)
		{
			m_list.RemoveAt(index);
		}

		public bool Remove(OracleJsonValue item)
		{
			return m_list.Remove(item);
		}

		public void Add(OracleJsonValue item)
		{
			CheckNull(item);
			m_list.Add(item);
		}

		public bool Contains(OracleJsonValue item)
		{
			return m_list.Contains(item);
		}

		public void CopyTo(OracleJsonValue[] array, int arrayIndex)
		{
			m_list.CopyTo(array, arrayIndex);
		}

		IEnumerator<OracleJsonValue> IEnumerable<OracleJsonValue>.GetEnumerator()
		{
			return m_list.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return m_list.GetEnumerator();
		}

		public bool IsEmpty()
		{
			return m_list.Count == 0;
		}

		public List<OracleJsonValue>.Enumerator Iterator()
		{
			return m_list.GetEnumerator();
		}

		public object[] ToArray()
		{
			return m_list.ToArray();
		}

		public void Clear()
		{
			m_list.Clear();
		}

		public OracleJsonValue Get(int index)
		{
			return m_list[index];
		}

		public int IndexOf(object o)
		{
			return m_list.IndexOf((OracleJsonValue)o);
		}

		internal int LastIndexOf(object o)
		{
			return m_list.LastIndexOf((OracleJsonValue)o);
		}

		internal string GetString(int index)
		{
			return m_list[index].AsJsonString().GetJsonString();
		}

		internal int GetInt(int index)
		{
			return ((OracleJsonNumber)m_list[index]).IntValue();
		}

		internal double GetDouble(int index)
		{
			return ((OracleJsonNumber)m_list[index]).DoubleValue();
		}

		internal decimal GetBigDecimal(int index)
		{
			return ((OracleJsonNumber)m_list[index]).BigDecimalValue();
		}

		internal long GetLong(int index)
		{
			return ((OracleJsonNumber)m_list[index]).LongValue();
		}

		internal bool GetBoolean(int index)
		{
			OracleJsonValue oracleJsonValue = m_list[index];
			if (oracleJsonValue.Equals(OracleJsonValue.TRUE))
			{
				return true;
			}
			if (oracleJsonValue.Equals(OracleJsonValue.FALSE))
			{
				return false;
			}
			throw new InvalidCastException();
		}

		internal bool IsNull(int index)
		{
			return OracleJsonValue.NULL.Equals(m_list[index]);
		}

		internal DateTime GetInstant(int index)
		{
			OracleJsonValue oracleJsonValue = m_list[index];
			if (oracleJsonValue.GetOracleJsonType() == OracleJsonType.DATE)
			{
				return oracleJsonValue.AsJsonDate().GetDateTime();
			}
			return oracleJsonValue.AsJsonTimestamp().GetDateTime();
		}

		internal byte[] GetBytes(int index)
		{
			return m_list[index].AsJsonBinary().GetBytes();
		}

		internal OracleJsonArray SubList(int fromIndex, int toIndex)
		{
			OracleJsonArray oracleJsonArray = new OracleJsonArray();
			for (int i = fromIndex; i < toIndex; i++)
			{
				oracleJsonArray.Add(Get(i));
			}
			return oracleJsonArray;
		}

		internal void Add(double value)
		{
			m_list.Add(new OracleJsonDouble(value));
		}

		internal void Add(long value)
		{
			m_list.Add(new OracleJsonDecimal(value));
		}

		internal void Add(decimal value)
		{
			m_list.Add(new OracleJsonDecimal(value));
		}

		internal void Add(bool value)
		{
			m_list.Add(value ? OracleJsonValue.TRUE : OracleJsonValue.FALSE);
		}

		internal void Add(string value)
		{
			m_list.Add(new OracleJsonString(value.ToCharArray()));
		}

		internal void Add(int value)
		{
			m_list.Add(new OracleJsonDecimal(value));
		}

		internal bool AddAll(List<OracleJsonValue> c)
		{
			foreach (OracleJsonValue item in c)
			{
				CheckNull(item);
				m_list.Add(item);
			}
			return c.Count > 0;
		}

		internal OracleJsonValue Set(int index, bool value)
		{
			return m_list[index] = (value ? OracleJsonValue.TRUE : OracleJsonValue.FALSE);
		}

		internal void Add(int index, OracleJsonValue element)
		{
			CheckNull(element);
			m_list[index] = element;
		}

		private void CheckNull(OracleJsonValue element)
		{
			if (element == null)
			{
				throw new NullReferenceException();
			}
		}

		internal OracleJsonValue Remove(int index)
		{
			OracleJsonValue oracleJsonValue = m_list[index];
			if (oracleJsonValue != OracleJsonValue.NULL)
			{
				m_list.RemoveAt(index);
			}
			return oracleJsonValue;
		}

		internal OracleJsonValue Set(int index, int value)
		{
			return m_list[index] = new OracleJsonDecimal(value);
		}

		internal OracleJsonValue Set(int index, double value)
		{
			return m_list[index] = new OracleJsonDouble(value);
		}

		internal OracleJsonValue Set(int index, long value)
		{
			return m_list[index] = new OracleJsonDecimal(value);
		}

		internal OracleJsonValue Set(int index, decimal value)
		{
			return m_list[index] = new OracleJsonDecimal(value);
		}

		internal OracleJsonValue SetNull(int index)
		{
			return m_list[index] = OracleJsonValue.NULL;
		}

		internal void DDNull()
		{
			m_list.Add(OracleJsonValue.NULL);
		}

		internal OracleJsonValue Set(int index, DateTime value)
		{
			return m_list[index] = new OracleJsonTimestamp(value);
		}

		internal void Add(DateTime value)
		{
			m_list.Add(new OracleJsonTimestamp(value));
		}

		internal OracleJsonValue Set(int index, byte[] value)
		{
			return m_list[index] = new OracleJsonBinary(value, isId: false);
		}

		internal void Add(byte[] value)
		{
			m_list.Add(new OracleJsonBinary(value, isId: false));
		}

		public override string ToJsonString()
		{
			StringWriter stringWriter = new StringWriter();
			OracleJsonSerializer oracleJsonSerializer = new OracleJsonSerializer(stringWriter);
			oracleJsonSerializer.Write(this);
			oracleJsonSerializer.Close();
			return stringWriter.ToString();
		}
	}
}
